#include "misc_impl.h"
#include "../tools/head.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    misc_impl::misc_impl()
    {
    }

    misc_impl::~misc_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int misc_impl::init()
    {
        int nRet = 0;
        return nRet;
    }

    int misc_impl::term()
    {
        int nRet = 0;
        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // utf8 to wchar
    // 
    int misc_impl::utf8_to_wchar( const char * lpszSrc, int nSrcByteSize, wchar_t * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;
        nRet = misc_tool::utf8_to_wchar( lpszSrc, nSrcByteSize, lpszDest, nDestByteSize, lpnDestNeedSize );
        return nRet;
    }

    // 
    // wcharto utf8
    // 
    int misc_impl::wchar_to_utf8( const wchar_t * lpszSrc, int nSrcByteSize, char * lpszDest, int nDestByteSize, int * lpnDestNeedSize )
    {
        int nRet = 0;
        nRet = misc_tool::wchar_to_utf8( lpszSrc, nSrcByteSize, lpszDest, nDestByteSize, lpnDestNeedSize );
        return nRet;
    }

    // 
    // get process full file name
    // 
    int misc_impl::get_process_file_full_name( char * pszFile, int nLen, int * pnLenNeeded )
    {
        int nRet = 0;

        WCHAR szFile[4096] = { 0 };

        if( 0 == nRet )
        {
            if( !pszFile )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            ::GetModuleFileNameW( 0, szFile, sizeof( szFile ) / sizeof( szFile[0] ) );
            nRet = misc_tool::wchar_to_utf8( szFile, -1, pszFile, nLen, pnLenNeeded );
        }

        return nRet;
    }

    // 
    // get process file path. including '\\' or '/'
    //
    int misc_impl::get_process_path( char * pszPath, int nLen, int * pnLenNeeded )
    {
        int nRet = 0;

        WCHAR szFile[4096] = { 0 };

        ::GetModuleFileNameW( 0, szFile, sizeof( szFile ) / sizeof( szFile[0] ) );

        WCHAR * p = 0, * pp = szFile;

        while( *pp != 0 )
        {
            if( *pp == L'\\' )
            {
                p = pp;
            }

            ++pp;
        }

        if( p )
        {
            *p = 0;
        }

        if( pszPath )
        {
            nRet = misc_tool::wchar_to_utf8( szFile, -1, pszPath, nLen, pnLenNeeded );
        }
        else
        {
            nRet = 1;
        }

        return nRet;
    }

    // 
    // append path in all platform
    // 
    int misc_impl::path_append( char * lpszPath, const char * lpszAdder )
    {
        int nRet = 0;
        PathAppendA( lpszPath, lpszAdder );
        return nRet;
    }

    // 
    // create guid
    // 
    int misc_impl::create_guid( char * lpszGuid )
    {
        int nRet = 0;

        USES_CONVERSION;

        if( lpszGuid )
        {
            GUID guid = { 0 };
            CoCreateGuid( &guid );
            CComBSTR bstr( guid );
            lstrcpyA( lpszGuid, W2CA( bstr.m_str ) );
        }

        return nRet;
    }

    // 
    // sleep 1 / 1000 second
    // 
    int misc_impl::sleep( int nMilliseconds )
    {
        int nRet = 0;
        Sleep( nMilliseconds );
        return nRet;
    }

    // 
    // output debug info
    // 
    int misc_impl::out_put_debug_string( const char * lpszInfo )
    {
        int nRet = 0;
        OutputDebugStringA( lpszInfo );
        return nRet;
    }

    int misc_impl::out_put_to_cmd( const char * lpszInfo )
    {
        using namespace std;
        int nRet = 0;
        cout << lpszInfo << endl;
        return nRet;
    }

    int misc_impl::trace( const char * lpszFormat, ... )
    {
        using namespace std;

        int nRet = 0;

        const int N = 1024 * 100;
        char buf[N] = { 0 };

        va_list  va;
        va_start( va, lpszFormat );
        nRet = vsnprintf_s( buf, N, _TRUNCATE, lpszFormat, va );
        va_end( va );

        OutputDebugStringA( buf );
        cout << buf << endl;

        return nRet;
    }

    // 
    // get seconds from since 1970-1-1
    // 
    // 
    // get seconds from since 1970-1-1
    // 
    xos_u64 misc_impl::get_wall_second( xos_u64 * lpWallSecond )
    {
        xos_u64 xRet = ( xos_u64 )time( 0 );
        *lpWallSecond = xRet;
        return xRet;
    }

    // 
    // get process ID
    // 
    xos_u64 misc_impl::get_current_process_id()
    {
        xos_u64 xRet = GetCurrentProcessId();
        return xRet;
    }

    // 
    // get thread ID
    // 
    xos_u64 misc_impl::get_current_thread_id()
    {
        xos_u64 xRet = GetCurrentThreadId();
        return xRet;
    }

    // 
    // get cpu num
    // 
    int misc_impl::get_cpu_num()
    {
        int nRet = 1;

        SYSTEM_INFO info = { 0 };

        GetSystemInfo( &info );

        if( info.dwNumberOfProcessors > 0 )
        {
            nRet = info.dwNumberOfProcessors; 
        }

        return nRet;
    }

    // 
    // release
    //
    int misc_impl::release()
    {
        int nRet = 0;

        term();
        put_back_lock();

        return nRet;
    }
} // xos
